package net.entelijan.cobean.notification;

import static org.junit.Assert.assertEquals;

import java.util.List;

import net.entelijan.cobean.core.ICobean;
import net.entelijan.cobean.core.impl.IPropertyChangeListenerAware;
import net.entelijan.cobean.text.DefaultTextInitializer;
import net.entelijan.cobean.util.CobeanUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fest.swing.fixture.FrameFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.junit.Test;

public class TextNotificationFestTestCase {

	private static Log log = LogFactory
			.getLog(TextNotificationFestTestCase.class);

	@Test
	public void test() {
		TextNotificationTestFrame frame = new TextNotificationTestFrame("TF");
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			final JTextComponentFixture leftTextBox = frameFix
					.textBox("leftTextField");
			final JTextComponentFixture rightTextBox = frameFix
					.textBox("rightTextField");

			final RecordingPropertyChangeListener nb = new RecordingPropertyChangeListener("value");
			final ICobean<String> cobean = init(frame, nb);
			log.debug("---(0)-----------------------------------------------");
			cobean.setValue("Hallo");
			log.debug("---(1)-----------------------------------------------");
			leftTextBox.requireText("Hallo");
			log.debug("---(2)-----------------------------------------------");
			assertEquals(1, nb.getNotificationCount());
			log.debug("---(3)-----------------------------------------------");
			leftTextBox.focus();
			log.debug("---(4)-----------------------------------------------");
			rightTextBox.focus();
			log.debug("---(5)-----------------------------------------------");
			assertEquals(1, nb.getNotificationCount());
			leftTextBox.setText("Hallo");
			rightTextBox.focus();
			assertEquals(1, nb.getNotificationCount());
			leftTextBox.setText("Hall");
			rightTextBox.focus();
			pause();
			assertEquals(2, nb.getNotificationCount());
			leftTextBox.setText("Hall");
			rightTextBox.focus();
			pause();
			assertEquals(2, nb.getNotificationCount());
			leftTextBox.setText("Hallo");
			rightTextBox.focus();
			pause();
			assertEquals(3, nb.getNotificationCount());
			cobean.setValue("Ditschi");
			assertEquals(4, nb.getNotificationCount());

			final List<EventContentBean> eventContents = nb.getEventContents();
			assertEventContentBean(null, "Hallo", "value", eventContents.get(0));
			assertEventContentBean("Hallo", "Hall", "value", eventContents
					.get(1));
			assertEventContentBean("Hall", "Hallo", "value", eventContents
					.get(2));
			assertEventContentBean("Hallo", "Ditschi", "value", eventContents
					.get(3));
		} finally {
			frameFix.cleanUp();
		}

	}

	private <T> void assertEventContentBean(Object oldValue, Object newValue,
			String propertyName, EventContentBean eventContentBean) {
		assertEquals(oldValue, eventContentBean.getOldValue());
		assertEquals(newValue, eventContentBean.getNewValue());
		assertEquals(propertyName, eventContentBean.getPropertyName());

	}

	private synchronized void pause() {
		try {
			this.wait(100);
		} catch (InterruptedException e) {
			// Can be ignored
		}
	}

	private ICobean<String> init(TextNotificationTestFrame frame,
			final RecordingPropertyChangeListener testListener) {
		final DefaultTextInitializer<String> ini = new DefaultTextInitializer<String>();
		ini.setCoTextComponent(frame.getLeftTextField());
		final ICobean<String> cobean = ini.initialize();
		log.debug("Created cobean: " + cobean);
		if (cobean instanceof IPropertyChangeListenerAware) {
			log.debug(cobean + " is IPropertyChangeListenerAware");
			((IPropertyChangeListenerAware) cobean)
					.setPropertyChangeListener(testListener);
		} else {
			log.debug(cobean + " is NOT IPropertyChangeListenerAware");
			CobeanUtil.addPropertyChangeListenerUsingReflection(cobean, testListener);
		}
		return cobean;
	}

}
